﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using HenIT.Data.SqlClient;
using System.Threading;
using System.IO;

namespace EventScavenger
{
    public partial class EventCollector : ServiceBase
    {
        private List<EventCollectorInstance> instances = new List<EventCollectorInstance>();
        private string serviceEventSource = "Event Collector";
        private EventScavengerDAL eventScavengerDAL;

        public EventCollector()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            #region Waiting for debugging
#if DEBUG
            //The following code is simply to ease attaching the debugger to the service to debug the startup routine
            DateTime startTime = DateTime.Now;
            while ((!Debugger.IsAttached) && ((TimeSpan)DateTime.Now.Subtract(startTime)).TotalSeconds < 20)  // Waiting until debugger is attached
            {
                RequestAdditionalTime(1000);  // Prevents the service from timeout
                Thread.Sleep(1000);           // Gives you time to attach the debugger   
            }
            // increase as needed to prevent timeouts
            RequestAdditionalTime(5000);     // for Debugging the OnStart method,     
#endif
            #endregion

            eventScavengerDAL = new EventScavengerDAL();
            eventScavengerDAL.SetConnection(Properties.Settings.Default.SqlServer, Properties.Settings.Default.Database);

            if (Properties.Settings.Default.EventLogs != null)
            {
                foreach (string eventLogName in Properties.Settings.Default.EventLogs)
                {
                    try
                    {
                        EventCollectorInstance eventCollectorInstance = new EventCollectorInstance(eventLogName);
                        instances.Add(eventCollectorInstance);
                        eventCollectorInstance.MessageReceived += new MessageReceivedDelegate(eventCollectorInstance_MessageReceived);
                        eventCollectorInstance.Start();
                    }
                    catch (Exception ex)
                    {
                        string moreErrordetails = string.Format("Attempting to add collector for {0}\r\n{1}", eventLogName, ex.ToString());
                        LogError(moreErrordetails, 0);
                    }
                }
            }
        }

        private Mutex reportMessageMutex = new Mutex();
        private void eventCollectorInstance_MessageReceived(EventCollectorInstance instance, Stream xmlStream)
        {
            try
            {
                reportMessageMutex.WaitOne();

                eventScavengerDAL.InsertEventLogEntries(xmlStream);
                if (Properties.Settings.Default.UpdateLastPollingTime)
                {
                    if (instance.LastMessageRaised.AddSeconds(3) < DateTime.Now)
                    {
                        eventScavengerDAL.SetLastMachineLogPollingTime(instance.MachineName, instance.EventLogName, DateTime.Now);
                    }
                }
            }
            catch (Exception ex)
            {
                LogError(ex.ToString(), 0);
            }
            finally
            {
                reportMessageMutex.ReleaseMutex();
            }
        }

        protected override void OnStop()
        {
            foreach (EventCollectorInstance eventCollectorInstance in instances)
            {
                eventCollectorInstance.Stop();
            }
            instances.Clear();
            instances = null;
            eventScavengerDAL.CloseConnection();
            eventScavengerDAL = null;
        }

        private void LogError(string message, int eventId)
        {
            EventLog.WriteEntry(serviceEventSource, message, EventLogEntryType.Error, 0);
        }
    }
}
